home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / pb3brows.zip / ABROWSE.BAS next >
BASIC Source File  |  1993-04-02  |  14KB  |  460 lines

  1. '******************************************************************************
  2. '*           PowerBasic 3 assembler module for viewing files                  *
  3. '*                    Use with   module BROWSE.BAS                            *
  4. '*                     (c) Hans Lunsing - 04/1993                             *
  5. '******************************************************************************
  6.  
  7. $DIM ARRAY
  8. $ERROR ALL -
  9. $LIB LPT -, COM -, GRAPH -, FULLFLOAT -, IPRINT -
  10. $OPTIMIZE SIZE
  11. $OPTION CNTLBREAK -, GOSUB +
  12. $STRING 1
  13.  
  14. DEFWRD A-Z       ' <========================================= IMPORTANT!!!!!
  15.  
  16. $INCLUDE "GENERAL.BI"
  17.  
  18. SHARED Handle%     ' [BX+00] Filehandle
  19. SHARED FilePtr&    ' [BX+02] Filepointer, Low byte
  20.                          ' [BX+04] Filepointer, High byte
  21. SHARED CacheSize   ' [BX+06] Cache size in WORDS
  22. SHARED CacheSeg    ' [BX+08] Cache Segment
  23. SHARED LowCache    ' [BX+10] offset Low  cache part
  24. SHARED HighCache   ' [BX+12] offset High cache part
  25. SHARED EndCache    ' [BX+14] offset end of active cache
  26. SHARED CachePtr    ' [BX+16] cachepointer
  27.  
  28. SUB ShowFile (BYVAL FirstRow%, BYVAL TextRows%, BYVAL BeginColumn%, _
  29.     BYVAL TextAttr%, BYVAL Filter%) PUBLIC
  30.  
  31.   LOCAL BeginOffset, EndColumn%, GlobalOfs, VideoOffs%, VideoSeg%
  32.  
  33.   IF Handle% < 0 THEN EXIT SUB
  34.   CALL GetVideoAddress (VideoSeg%, VideoOffs%)
  35.   GlobalOfs = VARPTR(Handle%)
  36.  
  37.   EndColumn% = BeginColumn% + pbvScrnCols
  38.   BeginOffset = CWRD(FirstRow% - 1) * pbvScrnCols * 2
  39.  
  40.   !MOV     BX, GlobalOfs
  41.   !MOV     ES, VideoSeg%               'Put segment video page in ES
  42.   !MOV     SI, [BX+16]               'Put cachepointer in SI
  43.   !XOR     DL,DL                      'Make linecounter 0
  44.   !MOV     DH,BYTE PTR TextRows%     'Max number of lines in DH
  45.  
  46. SFNextLine:
  47.   !CALL  NEAR PTR OffsLine
  48.   !XOR     BX,BX                       'Make positioncounter 0
  49.  
  50. SFNextByte:
  51.   !PUSH  BX
  52.   !MOV     BX, GlobalOfs
  53.   !CALL  NEAR PTR GetNextByte        'Load next byte in AL
  54.   !POP     BX
  55.  
  56.   !JC     SFFinish                       'Ready if carryflag
  57.   !AND     AL,BYTE PTR Filter%        'Wordstar filter
  58.   !CMP     AL,%CR                        'Is it CR ?
  59.   !JZ     SFNextByte                       'Yes, get next byte
  60.   !CMP     AL,%LF                        'Is it LF ?
  61.   !JZ     SFEndLine                       'Yes, process line
  62.   !CMP     AL,%TAB                       'Is it TAB ?
  63.   !JZ     SFTAB                           'Yes, process TAB
  64.   !MOV     CX, 1                       'Normal character:
  65.                                             'repeatcounter to 1
  66.  
  67. SFNormChar:
  68.   !CMP     BX,BeginColumn%           'Compare positioncounter to start column
  69.   !JC     SFEndByte                       'If smaller: skip
  70.   !CMP     BX,EndColumn%               'Compare positioncounter to end column
  71.   !JNC     SFEndByte                   'If >= : skip
  72.   !MOV     AH,BYTE PTR TextAttr%     'Put attribute in AH
  73.   !CMP     pbvScrnCard, %CGA 'CGA ? (all bits of pbvScrnCard except bit 1 are 0)
  74.   !JZ     SFCGA                           'yes, process separately
  75.   !STOSW                                   'put character and attrib on the scherm
  76.   !JMP     SFEndByte
  77.  
  78.   'CGA: wait for horizontal retrace (sync)
  79. SFCGA:
  80.   !PUSH    AX
  81.   !PUSH    DX
  82.   !MOV       DX, &H3DA
  83.   !CLI               'disable interrupts
  84. SFL1:
  85.   !IN       AL,DX           ' Read video status
  86.   !TEST    AL,1        ' horizontal retrace active ?
  87.   !JNZ       SFL1        ' yes, wait until done
  88. SFL2:
  89.   !IN       AL,DX           ' No, Read status
  90.   !TEST    AL,1        ' and wait for retrace
  91.   !JZ       SFL2
  92.   !POP       DX
  93.   !POP       AX
  94.   !STOSW
  95.   !STI                   'enable interrupts
  96.  
  97. SFEndByte:
  98.   !INC     BX               'increment positioncounter
  99.   !LOOP  SFNormChar          'repeat until CX = 0
  100.   !JMP     SFNextByte       'get next byte
  101.  
  102. SFTAB:
  103.   !MOV     AX,BX           'positioncounter in AX
  104.   !AND     AX,7               'position modulo 8
  105.   !MOV     CX,8               '8 in CX
  106.   !SUB     CX,AX           'subtract position mod 8
  107.   !MOV     AL,32           'load space in AL
  108.   !JMP     SFNormChar       'Repeat CX times on the screen
  109.  
  110. SFEndLine:
  111.   !CALL  NEAR PTR FillLine
  112.   !INC     DX               'increment line counter  (INC DL doesnot work in pb3)
  113.   !CMP     DL,DH           'equals screen lines ?
  114.   !JC     SFNextLine           'No, get next line
  115.  
  116. SFFinish:
  117.   !CMP     AL,%LF            'last read character  LF ?
  118.   !JZ     SFL0                   'No, fill with spaces
  119.   !CALL  NEAR PTR FillLine
  120.   !INC     DX               'And increment linecounter(INC DL but not in pb3)
  121. SFL0:
  122.   !CMP     DL, DH            'all screenlines occupied ?
  123.   !JNC     SFExit            'yes, ready!
  124.   !CALL  NEAR PTR OffsLine 'Calculate offset new line
  125.   !MOV     AL, DH            'calculate remaining positions
  126.   !SUB     AL, DL            'on the screen in CX
  127.   !MUL     pbvScrnCols
  128.   !MOV     CX, AX
  129.   !CALL  NEAR PTR PlaceSpaces  'Clear the rest of the screen
  130.  
  131. SFExit:
  132.   EXIT SUB
  133.  
  134. OffsLine:
  135.   !MOV     AL,BYTE PTR pbvScrnCols     'Put Number of videocolumns in AL,
  136.   !MUL     DL                               'Multiply by number of lines
  137.                                                 'uptil now
  138.   !SHL     AX,1                               'multiply by 2 (byte -> woord)
  139.   !MOV     DI,AX                           'result in DI
  140.   !ADD     DI,VideoOffs%                   'add video page plus first line
  141.   !ADD     DI,BeginOffset            'to get offset to the next line.
  142.   !RETN
  143.  
  144. FillLine:
  145.   !CMP     BX,EndColumn%                   'Compare postioncounter to end column
  146.   !JNC     FLExit                               'If =>: ready
  147.   !CMP     BX,BeginColumn%               'compare positioncounter to start column
  148.   !JNC     FLL0                                  'If =>: continue
  149.   !MOV     BX, BeginColumn%
  150. FLL0:
  151.   !MOV     CX, EndColumn%
  152.   !SUB     CX, BX                            'CX = number of positions to clear
  153.   !PUSH  AX
  154.   !CALL  NEAR PTR PlaceSpaces          'Clear the rest of the line
  155.   !POP     AX
  156. FLExit:
  157.   !RETN
  158.  
  159. PlaceSpaces:
  160.   !MOV     AL,32                               'AX = space + attribute
  161.   !MOV     AH,BYTE PTR TextAttr%
  162.   !REP     STOSW                               'Clear rest of the screen
  163.   !RETN
  164.  
  165. END SUB
  166.  
  167. SUB InitBrowseFile (BYVAL FHandle, BYVAL CSeg, BYVAL COffs, BYVAL CSize) PUBLIC
  168.   Handle% = FHandle
  169.   CacheSeg = CSeg
  170.   LowCache = COffs
  171.   CacheSize = CSize
  172.   HighCache = LowCache + CacheSize
  173.   CALL HomeFile
  174. END SUB
  175.  
  176. SUB ExitBrowseFile  PUBLIC
  177.   Handle% = -1
  178. END SUB
  179.  
  180. SUB LineDown PUBLIC
  181.   LOCAL GlobalOfs
  182.   IF Handle% < 1 THEN EXIT SUB
  183.   GlobalOfs = VARPTR(Handle%)
  184.   !MOV     BX, GlobalOfs
  185.   !PUSH  SI
  186.   !MOV     SI, [BX+16]       'cachepointer in SI
  187.   !CALL  NEAR PTR  ScanDown
  188.   !MOV     [BX+16], SI       'update cachepointer
  189.   !POP     SI
  190. END SUB
  191.  
  192. SUB LineUp PUBLIC
  193.   LOCAL GlobalOfs
  194.   IF Handle% < 1 THEN EXIT SUB
  195.   GlobalOfs = VARPTR(Handle%)
  196.   !MOV     BX, GlobalOfs
  197.   !PUSH  SI
  198.   !MOV     SI, [BX+16]       'cachepointer in SI
  199.   !CALL  NEAR PTR ScanUp
  200.   !MOV     [BX+16], SI       'update cachepointer
  201.   !POP   SI
  202. END SUB
  203.  
  204. SUB PageDown (BYVAL TextRows%) PUBLIC
  205.   LOCAL GlobalOfs
  206.   IF Handle% < 1 THEN EXIT SUB
  207.   GlobalOfs = VARPTR(Handle%)
  208.   !MOV     BX, GlobalOfs
  209.   !PUSH  SI
  210.   !MOV     SI, [BX+16]       'cachepointer in SI
  211.   !MOV     CX, TextRows%
  212. PDL0:
  213.   !CALL  NEAR PTR ScanDown            'as many lines Down as
  214.   !LOOP  PDL0                           'textlines on the screen
  215.   !MOV     [BX+16], SI               'update cachepointer
  216.   !POP     SI
  217. END SUB
  218.  
  219. SUB PageUp (BYVAL TextRows%) PUBLIC
  220.   LOCAL GlobalOfs
  221.   IF Handle% < 1 THEN EXIT SUB
  222.   GlobalOfs = VARPTR(Handle%)
  223.   !MOV     BX, GlobalOfs
  224.   !PUSH  SI
  225.   !MOV     SI, [BX+16]               'cachepointer in SI
  226.   !MOV     CX, TextRows%
  227. PUL0:
  228.   !CALL  NEAR PTR ScanUp            'as many lines Up as
  229.   !LOOP  PUL0                           'textlines on the screen
  230.   !MOV     [BX+16], SI               'update cachepointer
  231.   !POP     SI
  232. END SUB
  233.  
  234. SUB HomeFile PUBLIC
  235.   LOCAL GlobalOfs
  236.   IF Handle% < 1 THEN EXIT SUB
  237.   GlobalOfs = VARPTR(Handle%)
  238.   FilePtr& = 0
  239.   CachePtr = LowCache
  240.   !MOV     BX, GlobalOfs
  241.   !MOV     DX, [BX+10]               'startaddress low cache in DX
  242.   !MOV     CX, [BX+06]               'cachesize in CX
  243.   !SHL     CX,1                           'multiply 2 is number of bytes read
  244.   !CALL  NEAR PTR FileToCache       'Read bytes from file in cache
  245. END SUB
  246.  
  247. SUB EndFile(BYVAL TextRows%) PUBLIC
  248.   LOCAL GlobalOfs
  249.   IF Handle% < 1 THEN EXIT SUB
  250.   GlobalOfs = VARPTR(Handle%)
  251.   !MOV     BX, GlobalOfs
  252.   !PUSH  SI
  253.   !MOV     SI, [BX+16]               'cachepointer in SI
  254. EFL0:
  255.   !PUSH  SI                               'Save cachepointer
  256.   !CALL  NEAR PTR ScanDown            'nextline
  257.   !POP     AX                               'Restore old pointer
  258.   !CMP     AX,SI                       'compare old and new pointer
  259.   !JNZ     EFL0                           'continue if equal
  260.   !MOV     CX, TextRows%               'Put pointer to start of nextscreen
  261. EFL1:
  262.   !CALL  NEAR PTR ScanUp            'pageup
  263.   !LOOP  EFL1
  264.   !MOV     [BX+16], SI               'update cachepointer
  265.   !POP     SI
  266. END SUB
  267.  
  268. '-----------------------------------------------------------------------------
  269.  
  270. GetNextByte:
  271.   !CMP     SI,[BX+14]                   'is cachepointer end of active cache or >
  272.   !JC     GNBL0
  273.   !JMP     GNBExit                       'yes, return with carry (ready)
  274.                                             'Direct short jump to GNBExit is not possible
  275.                                             'because of the basicstatements in between
  276. GNBL0:
  277.   !MOV     AX, [BX+06]
  278.   !SHL     AX, 1                       'cachepointer to end of highcache or up?
  279.   !CMP     SI, AX
  280.   !JNC     GNBL1
  281.   !JMP     GNBLoadNext               'No, load byte in AL
  282.                                             'and return without carry
  283.                                             'yes, move contents highcache to lowcache
  284.                                             'read part of file in highcache:
  285.                                             'Save registers CX, DX, DI and ES
  286. GNBL1:
  287.   !PUSH  CX           'loopcounter PgUp/PgDn
  288.   !PUSH  DX           'linecounter
  289.   !PUSH  DI           'screenoffset
  290.   !PUSH  ES           'screensegment
  291.                         'Contents high cache to low:
  292.   !MOV     SI, [BX+12]       'Let SI be source
  293.   !MOV     DI, [BX+10]       'and DI be destination
  294.   !MOV     CX, [BX+06]       'Put (half the) CacheSize in CX
  295.   !PUSH  DS
  296.   !MOV     ES, [BX+08]       'ES and DS point to
  297.   !PUSH  ES                       'cachesegment
  298.   !POP     DS
  299.   !REPZ  MOVSB                   'move contents of the cache
  300.   !POP     DS
  301.  
  302.                                     'Fill high cache from file:
  303.   FilePtr& = FilePtr& + 2 * CacheSize  ' filepointer
  304.  
  305.   !MOV     SI, DI                       'SI points to end of low cache
  306.   !MOV     CX, [BX+06]              'Zet CacheSize in CX
  307.   !MOV     DX, [BX+12]              'DX points to high cache
  308.   !CALL  NEAR PTR FileToCache    'read CacheSize bytes from file into high cache
  309.  
  310.   CachePtr = CachePtr - CacheSize 'Update cachepointer
  311.   FilePtr& = FilePtr& - CacheSize 'update filepointer for next read
  312.   !POP     ES                              'Restore registers
  313.   !POP     DI
  314.   !POP     DX
  315.   !POP     CX
  316.   !JMP     GetNextByte           'load first byte
  317.  
  318. GNBLoadNext:
  319.   !PUSH  DS
  320.   !MOV     DS, [BX+08]
  321.   !LODSB                               'Load byte in AL and update SI
  322.   !POP     DS
  323.  
  324. GNBExit:
  325.   !CMC                               'Complement carry flag.
  326.   !RETN
  327.  
  328. '-----------------------------------------------------------------------------
  329.  
  330. GetPreviousByte:
  331.   !CMP     SI, [BX+10]       'cachepointer past start
  332.                'lage cache ?
  333.   !JBE     GPBL0
  334.   !JMP     GPBLoadPrev       'Yes, load previous byte and return
  335. GPBL0:
  336.   !MOV     AX, [BX+02]       'No:,
  337.   !OR     AX, [BX+04]           ' Filepointer  zero ?
  338.   !JNZ     GPBL1
  339.   !JMP     GPBExitC           'Yes, begin file found,
  340.                                     'return with carry
  341.                                     'No, move lowcache to high
  342.                                     'and fill low cache from file:
  343.                                     'save registers CX, DX, DI and ES
  344. GPBL1:
  345.   !PUSH  CX           'loopcounter PgUp/PgDn
  346.   !PUSH  DX           'linecounter
  347.   !PUSH  DI           'screenoffset
  348.   !PUSH  ES           'screensegment
  349.                         'contents low cache to high:
  350.   !MOV     SI, [BX+10]       'SI points to source
  351.   !MOV     DI, [BX+12]       'DI to destination
  352.   !MOV     CX, [BX+06]       '(half) CacheSize in CX
  353.   !PUSH  DS
  354.   !MOV     ES, [BX+08]       'ES and DS point to
  355.   !PUSH  ES                       'cachesegment
  356.   !POP     DS
  357.   !REPZ  MOVSB                   'Move contents cache
  358.   !POP     DS
  359.  
  360.                                     'Fill Low cache from file:
  361.   FilePtr& = FilePtr& - CacheSize 'file pointer
  362.  
  363.   !MOV     CX, [BX+06]          'CacheSize in CX
  364.   !MOV     DX, [BX+10]          'DX to low cache
  365.   !CALL  NEAR PTR FileToCache      'Read CacheSize bytes from file to low cache
  366.  
  367.   CachePtr = CachePtr + CacheSize 'Update cachepointer
  368.  
  369.   !POP     ES              'restore registers
  370.   !POP     DI
  371.   !POP     DX
  372.   !POP     CX
  373.  
  374. GPBLoadPrev:
  375.   !PUSH  DS
  376.   !MOV     DS, [BX+08]
  377.   !DEC     SI           'update SI
  378.   !MOV     AL, BYTE PTR [SI] 'Load byte in AL
  379.   !POP     DS
  380.  
  381.   !XOR     AH, AH
  382.   !RCR     AH, 1          'clear carry.CLC instruction does not work PB
  383.  
  384.   !JMP     GPBExit
  385. GPBExitC:
  386.   !STC               'set carry
  387. GPBExit:
  388.   !RETN
  389.  
  390. '-----------------------------------------------------------------------------
  391.  
  392. FileToCache:
  393.   !PUSH  BP
  394.   !MOV     BP, SP        ' stackframe
  395.                             ' save registers:
  396.   !PUSH  DS          ' [BP-02] default datasegment
  397.   !PUSH  BX          ' [BP-04] BX contains pointer to global shared vars
  398.   !PUSH  CX               ' CX contains number of bytes to read,
  399.   !PUSH  DX               ' DX contains offset to CacheSeg
  400.  
  401.   EndCache = 65535       ' end of Cache op FFFFh. assignment of
  402.                                 ' &HFFFF does not work properly.
  403.  
  404.   !MOV     DX, [BX+02]       ' put required position
  405.   !MOV     CX, [BX+04]       '     filepointer in CX:DX
  406.   !MOV     AL,0                   ' LSEEK with AL=0 -> byte offset
  407.                                     ' from start of file asked.
  408.   !MOV     AH, &H42
  409.   !MOV     BX, [BX]           ' filehandle in BX
  410.   !INT   &H21              ' move filepointer
  411.                                     ' new position in DX:AX (=CX:DX)
  412.   !MOV   BX, [BP-04]       ' restore BX
  413.   !MOV   CX, [BX]          ' handle temporary in CX
  414.   !MOV   DS, [BX+08]       ' segment cache in DS
  415.   !MOV   BX, CX            ' handle now in BX
  416.   !POP     DX                   ' restore DX and CX to read the file
  417.   !POP     CX
  418.   !MOV     AH, &H3F
  419.   !INT     &H21                   ' read bytes from file in cache
  420.   !POP     BX                   ' restore BX and DS
  421.   !POP   DS
  422.   !JNC     FTCL0               ' attempt ok: continue
  423.   !XOR     AX,AX               ' if not, zero bytes read
  424. FTCL0:
  425.   !CMP     AX,CX               ' Number of bytes read equal to
  426.                                     ' length half the cache ?
  427.   !JZ     FTCL1                      ' Yes, file not completely read
  428.   !ADD     AX,DX               ' No, calculate the end of the relevant cache
  429.                                     ' as offset cache scope plus number of bytes read
  430.   !MOV     [BX+14],AX           ' and save.
  431. FTCL1:
  432.   !POP   BP
  433.   !RETN
  434.  
  435. '-----------------------------------------------------------------------------
  436.  
  437. ScanDown:
  438.   !CALL  NEAR PTR GetNextByte       'Read next byte
  439.   !JC     SDExit                            'return if EOF
  440.   !CMP     AL,%LF                        'LineFeed ?
  441.   !JNZ     ScanDown                   'No,Next byte
  442. SDExit:
  443.   !RETN
  444.  
  445. '-----------------------------------------------------------------------------
  446.  
  447. ScanUp:
  448.   !CALL  NEAR PTR GetPreviousByte
  449.   !JC     SUExit        'return if begin file
  450. SULoop:
  451.   !CALL  NEAR PTR GetPreviousByte
  452.   !JC     SUExit        'return if begin file
  453.   !CMP     AL,%LF        'LineFeed ?
  454.   !JNZ     SULoop        'No, farther back again
  455.   !CALL  NEAR PTR GetNextByte        'yes, load byte after LF back
  456. SUExit:
  457.   !RETN
  458.  
  459.  
  460.